package com.platform.server.redis.impl;

import com.platform.server.redis.RedisDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
import redis.clients.jedis.exceptions.JedisException;

import java.util.List;
import java.util.Map;
import java.util.Set;


@Service
public class RedisClientTemplate {
	private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

    @Autowired
    private RedisDataSource redisDataSource;

    public void disconnect() {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        shardedJedis.disconnect();
    }

    /**
     * 设置值写入redis缓存
     *
     * @param sets
     * @param key
     * @param value
     * @return
     */
    public boolean hset(String sets, String key, String value) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        long result = 0;
        boolean broken = false;
        try {
            result = shardedJedis.hset(sets, key, value);
        }catch(JedisException e){
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result > 0 ? true : false;
        }
    }

    /**
     * 根据用户键值获取值
     *
     * @param sets
     * @param key
     * @return
     */
    public String hget(String sets, String key) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        String result = null;
        boolean broken = false;
        try {
            result = shardedJedis.hget(sets, key);
        } catch (JedisException e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    /**
     * 获取HSET中对象存储的数量
     *
     * @param sets
     * @return
     */
    public long hgetCount(String sets) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        long result = 0;
        boolean broken = false;
        try {
            result = shardedJedis.hlen(sets);
        } catch (JedisException e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    /**
     * 判断是否存在HSET中
     *
     * @param sets
     * @param key
     * @return
     */
    public boolean isExit(String sets, String key) {
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        String results = null;
        boolean broken = false;
        try {
            results = shardedJedis.hget(sets, key);
        } catch (JedisException e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return results == null ? false : true;
        }
    }

    public Long incr(String key) {
        Long incr = 0L;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            incr = shardedJedis.incr(key);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return incr;
        }
    }

    public boolean hmset(String key, Map<String, String> hash, int seconds) {
        boolean result = false;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            String hmset = shardedJedis.hmset(key, hash);
            if ("OK".equalsIgnoreCase(hmset)) {
                result = true;
            }
            shardedJedis.expire(key , seconds);
        } catch (Exception e) {
        	e.printStackTrace();
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public List<String> hmget(String key, String... fields) {
        List<String> result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.hmget(key, fields);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public Map<String, String> hgetAll(String key) {
        Map<String, String> result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.hgetAll(key);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public String getSet(final String key, final String value) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.getSet(key, value);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public String set(final String key, String value) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.set(key, value);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public String set(final String key, String value , int seconds) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.set(key, value);
            shardedJedis.expire(key , seconds);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public long del(final String key) {
        long result = 0;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.del(key);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }


    public String get(final String key) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.get(key);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public Long zadd(final String key, final double score, final String member) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.zadd(key, score, member);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public Set<String> zrange(final String key, final long start, final long end) {
        Set<String> result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.zrange(key, start, end);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    public Long zcard(final String key) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        try {
            result = shardedJedis.zcard(key);
        } catch (Exception e) {
            broken = true;
            if (null != shardedJedis) {
                redisDataSource.returnResource(shardedJedis,broken);
                shardedJedis = null;
            }
        } finally {
            if (null != shardedJedis)
                redisDataSource.returnResource(shardedJedis,broken);
            return result;
        }
    }

    /**
     * <p>通过key向list头部添加字符串</p>
     * @param key
     * @param strs 可以使一个string 也可以使string数组
     * @return 返回list的value个数
     */
    public Long lpush(String key ,String...strs){
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        Long res = null;
        try {
            res = shardedJedis.lpush(key, strs);
        } catch (Exception e) {
            broken = true;
            redisDataSource.returnResource(shardedJedis,broken);
            e.printStackTrace();
        } finally {
            if(shardedJedis!=null) {
                redisDataSource.returnResource(shardedJedis,broken);
            }
        }
        return res;
    }

    /**
     * <p>通过key从list尾部删除一个value,并返回该元素</p>
     * @param key
     * @return
     */
    public String rpop(String key){
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        String res = null;
        try {
            res = shardedJedis.rpop(key);
        } catch (Exception e) {
            broken = true;
            redisDataSource.returnResource(shardedJedis,broken);
            e.printStackTrace();
        } finally {
            if(shardedJedis!=null) {
                redisDataSource.returnResource(shardedJedis,broken);
            }
        }
        return res;
    }

    /**
     * 批量提交队列数据
     * @param key
     * @param strs
     */
    public void lmpush(String key ,List<String> strs){
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        boolean broken = false;
        Long res = null;
        try {
            ShardedJedisPipeline pipeline = shardedJedis.pipelined();
            for (String str : strs) {
                pipeline.lpush(key, str);
            }
            pipeline.sync();
        } catch (Exception e) {
            broken = true;
            redisDataSource.returnResource(shardedJedis,broken);
            e.printStackTrace();
        } finally {
            if(shardedJedis!=null) {
                redisDataSource.returnResource(shardedJedis,broken);
            }
        }
    }

    public String type(String key) {
        String result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.type(key);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 在某段时间后失效
     *
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(String key, int seconds) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.expire(key, seconds);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 在某个时间点失效
     * @param key
     * @param unixTime
     * @return
     */
    public Long expireAt(String key, long unixTime) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.expireAt(key, unixTime);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    //设置失效时间
    public Long expireAt(byte[] key, long unixTime) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.expireAt(key, unixTime);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

    /**
     * 返回该key的剩余有效时间
     * @param key
     * @return
     */
    public Long ttl(String key) {
        Long result = null;
        ShardedJedis shardedJedis = redisDataSource.getRedisClient();
        if (shardedJedis == null) {
            return result;
        }
        boolean broken = false;
        try {
            result = shardedJedis.ttl(key);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            broken = true;
        } finally {
            redisDataSource.returnResource(shardedJedis, broken);
        }
        return result;
    }

}
